using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint;
using Microsoft.Office.Server;
using Microsoft.Office.Server.Search.Query;
using System.Xml.Serialization;
using ASPNET_WebPart = System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint.Utilities;


namespace Microsoft.SharePoint.Search.Custom
{
    /// <summary>
    /// Class for the custom XML Viewer control. The default control
    /// does not accept connections from other controls to display data.
    /// This control allows for a custom XSLT and XML from a 
    /// connected webpart.
    /// <para>
    /// <list type="bullet">
    /// <item>http://msdn2.microsoft.com/en-us/library/ms469765.aspx</item>
    /// <item>http://msdn2.microsoft.com/en-us/library/ms551453.aspx</item>
    /// <item>http://msdn.microsoft.com/msdnmag/issues/06/02/BasicInstincts/</item>
    /// <item>http://msdn2.microsoft.com/en-us/library/ms499375.aspx</item>
    /// <item>http://msdn2.microsoft.com/en-us/library/ms546216.aspx</item>
    /// <item>http://msdn2.microsoft.com/en-us/library/bb219479.aspx</item>
    /// <item>http://msdn2.microsoft.com/en-us/library/ms519321.aspx</item>
    /// </list>
    /// </para>
    /// </summary>
    [XmlRoot(Namespace = "MicrosoftCustomSearch")]
    [DefaultProperty("XSLT"), ToolboxData("<{0}:MicrosoftCustomSearch runat=server></{0}:MicrosoftXMLViewControl>")]
    public class CustomXMLView:WebPart
	{
        /// <summary>
        /// XML data provider connected
        /// </summary>
		private IXMLData provider;

        /// <summary>
        /// XML Document from provider
        /// </summary>
		private System.Xml.XmlDocument xmlData = new System.Xml.XmlDocument();

        /// <summary>
        /// XSL Transform Document
        /// </summary>
		private System.Xml.XmlDocument xslData = new System.Xml.XmlDocument();

        /// <summary>
        /// XSLT Transform object
        /// </summary>
		private System.Xml.Xsl.XslCompiledTransform xslTransform = new System.Xml.Xsl.XslCompiledTransform();

        /// <summary>
        /// Default Transform 
        /// Document. Provides a listing of 
        /// all XML fields from the provider.
        /// </summary>
		const string defaultXSLT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n<xsl:output method=\"xml\" version=\"1.0\" encoding=\"UTF-8\" indent=\"yes\"/>\n<xsl:template match=\"/\">\n<xsl:copy-of select=\"*\"/>\n</xsl:template>\n</xsl:stylesheet>";

        /// <summary>
        /// XSLT Text String
        /// </summary>
        private string _xslText = defaultXSLT;

        ///Property to change the XSLT. The value 
        ///is only stored in the Shared Storage. 
        ///It can't be personalized.
		[Browsable(true), Category("XML Information")]
        [DefaultValue(""), WebPartStorage(Storage.Shared)]
        [FriendlyName("XSLT"), Description("XML Transform To Apply")]
        public string XSLText
		{
			get
			{
				return _xslText;
				}
			set
            {
				_xslText = value;
            }
		}

        /// <summary>
        /// Create child Controls as necessary.
        /// </summary>
		protected override void CreateChildControls()
		{
			//Create child controls when called.
			base.CreateChildControls();
		}

        /// <summary>
        /// Consume the provider data
        /// </summary>
        /// <param name="provider">Control that provides the data to be transformed. 
        /// It must implement the IXMLData interface</param>
		[ASPNET_WebPart.ConnectionConsumer("XML Consumer", "IXMLData")]
		public void SetConnectionInterface(IXMLData provider)
        {
			//Standard connection interface from MSDN sample.
			//Add to the collection of providers when necessary.
			this.provider = provider;
			
		}

        /// <summary>
        /// Check the XML from the provider if it is set.
        /// </summary>
		private void checkXML()
		{
			//Remove the existing XML data
            xmlData.RemoveAll();

            //If there is a provider set the XML data.
			if (!(this.provider == null))
			{
				xmlData=this.provider.XMLData;
			}

		}

        /// <summary>
        /// Check the XSLT to verify the 
        /// default is not needed.
        /// </summary>
		private void checkXSL()
		{
			xslData.RemoveAll();
			if (_xslText == null)
			{
				_xslText = defaultXSLT;
			}
			else if (_xslText == string.Empty)
			{
				_xslText = defaultXSLT;

			}

			xslData.LoadXml(_xslText);

	    }

		/// <summary>
		/// Render the web part.
		/// </summary>
		/// <param name="output">The HTML Writer to 
        /// output the transform to</param>
        protected override void RenderWebPart(HtmlTextWriter output )
	    {
		    ///Get the XML Data
            checkXML();

            ///Get the XSLT document
			checkXSL();

            ///Load the Transform
			xslTransform.Load(xslData);

            try
            {
                ///Transform the document and send to the writer
                xslTransform.Transform(xmlData, null, output);
            }
            catch (Exception ex)
            {
                ///Write error out to trace listener
                System.Diagnostics.Trace.TraceError("Exception: " + Environment.NewLine + ex.ToString());
                output.WriteEncodedText(ex.ToString().Replace("\n", Environment.NewLine + "<br />"));
            }
            finally
            {
                ///Flush trace statements out to listeners
                System.Diagnostics.Trace.Flush();
            }
	    }
	}

}